package core

import (
	"context"
	"time"

	"zstackgo/pkg/header/errorcode"
)

type FutureReturnValueCompletion[T, R any] struct {
	success   bool
	errorCode *errorcode.ErrorCode
	done      bool

	ctx   context.Context
	ctxFn context.CancelFunc

	Reqs   []T
	Result R
}

func NewFutureReturnValueCompletion[T, R any](one T, others ...T) *FutureReturnValueCompletion[T, R] {
	c := &FutureReturnValueCompletion[T, R]{}

	c.Reqs = append(c.Reqs, one)
	if len(others) > 0 {
		c.Reqs = append(c.Reqs, others...)
	}

	c.ctx, c.ctxFn = context.WithCancel(context.Background())

	return c
}

func (c *FutureReturnValueCompletion[T, R]) Wait(t int64) {
	select {
	case <-c.ctx.Done():
		return
	case <-time.After(time.Duration(t) * time.Millisecond):
		c.Fail(errorcode.NewErr("timeout", "timeout"))
		return
	}
}

func (c *FutureReturnValueCompletion[T, R]) Fail(er *errorcode.ErrorCode) {
	c.success = false
	c.errorCode = er
	c.done = true
}

func (c *FutureReturnValueCompletion[T, R]) Success(o R) {
	c.success = true
	c.done = true
	c.Result = o

	c.ctxFn()
}

func (c *FutureReturnValueCompletion[T, R]) GetResult() R {
	return c.Result
}
